import tkinter as tk
from tkinter import ttk
import ttkbootstrap as tb
import pyautogui
import easyocr
import pytesseract
import time
import hashlib
import uuid
import requests
import os
from bs4 import BeautifulSoup
import numpy as np

# 设置 Tesseract OCR 的路径，根据实际安装路径修改
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
file_path = os.path.join(desktop_path, 'translation_history.txt')
YOUDAO_URL = 'https://openapi.youdao.com/api'
APP_KEY = '3ec26aae9321262d'
APP_SECRET = 'xM5B9iKt3CXtAFsYv2rGUhvJptIrFLIj'

# 支持的语言列表
LANGUAGES = {
    '中文': 'zh-CHS',
    '英文': 'en',
    '日文': 'ja',
    '韩文': 'ko',
    '法文': 'fr',
    '德文': 'de',
    '俄文': 'ru'
}


def encrypt(signStr):
    hash_algorithm = hashlib.sha256()
    hash_algorithm.update(signStr.encode('utf-8'))
    return hash_algorithm.hexdigest()


def truncate(q):
    if q is None:
        return None
    size = len(q)
    return q if size <= 20 else q[0:10] + str(size) + q[size - 10:size]


def do_request(data):
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    response = requests.post(YOUDAO_URL, data=data, headers=headers)
    response.raise_for_status()  # 检查请求是否成功
    return response


# 参数分别为 需要翻译的语句 源语言id 目标语言id
# 返回值为翻译结果和音标
def translate(text, from_lang, to_lang):
    data = {
        'from': from_lang,
        'to': to_lang,
        'signType': 'v3',
        'curtime': str(int(time.time())),
        'appKey': APP_KEY,
        'q': text,
        'salt': str(uuid.uuid1()),
        'vocabId': ''  # 可选，用户词表ID
    }
    signStr = APP_KEY + truncate(text) + data['salt'] + data['curtime'] + APP_SECRET
    data['sign'] = encrypt(signStr)

    response = do_request(data)
    result = response.json()

    if result.get('errorCode') == '0':
        translation = result.get('translation')

        webdict_url = result.get('webdict', {}).get('url')
        if webdict_url:
            try:
                page_response = requests.get(webdict_url)
                page_response.raise_for_status()
                soup = BeautifulSoup(page_response.text, 'html.parser')

                # 提取单词
                word = soup.find('div', class_='ec').find('h2').find('span').text.strip()

                # 提取音标
                phonetic_spans = soup.find_all('span', class_='phonetic')
                phonetic = ', '.join([span.text.strip() for span in phonetic_spans])

                # 提取词性和翻译内容
                pos_translation_li = soup.find('div', class_='ec').find('ul').find_all('li')
                pos_translation = []
                for li in pos_translation_li:
                    pos_translation.append(li.text.strip())
                pos_translation_str = '\n'.join(pos_translation)

                return word, phonetic, pos_translation_str
            except Exception as e:
                print(f"抓取网页内容时出错: {e}")
                return text, "no phonetic", translation
        raise Exception("未找到 webdict URL 或抓取网页内容失败")
    else:
        raise Exception(f"Error: {result.get('errorCode')}, {result.get('errorMsg')}")


class SelectionWindow:
    def __init__(self, root):
        self.root = root
        self.start_x = None
        self.start_y = None
        self.end_x = None
        self.end_y = None

        # 创建透明顶层窗口
        self.selection_window = tk.Toplevel(root)
        self.selection_window.attributes('-fullscreen', True)
        self.selection_window.attributes('-alpha', 0.2)
        self.selection_window.overrideredirect(True)

        # 绑定鼠标事件
        self.selection_window.bind("<ButtonPress-1>", self.on_press)
        self.selection_window.bind("<B1-Motion>", self.on_drag)
        self.selection_window.bind("<ButtonRelease-1>", self.on_release)

        # 创建矩形框用于显示选择区域
        self.canvas = tk.Canvas(self.selection_window, highlightthickness=0)
        self.canvas.pack(fill=tk.BOTH, expand=True)
        self.rect = None

    def on_press(self, event):
        self.start_x = event.x
        self.start_y = event.y
        if self.rect:
            self.canvas.delete(self.rect)

    def on_drag(self, event):
        if self.start_x is not None and self.start_y is not None:
            if self.rect:
                self.canvas.delete(self.rect)
            self.end_x = event.x
            self.end_y = event.y
            self.rect = self.canvas.create_rectangle(
                self.start_x, self.start_y, self.end_x, self.end_y,
                outline='red', width=2
            )

    def on_release(self, event):
        if self.start_x is not None and self.start_y is not None:
            self.end_x = event.x
            self.end_y = event.y
            self.selection_window.destroy()

    def get_selection_coords(self):
        left = min(self.start_x, self.end_x)
        top = min(self.start_y, self.end_y)
        width = abs(self.end_x - self.start_x)
        height = abs(self.end_y - self.start_y)
        return left, top, width, height


def get_selection():
    root = tk.Tk()
    root.withdraw()
    selection = SelectionWindow(root)
    root.wait_window(selection.selection_window)
    left, top, width, height = selection.get_selection_coords()
    # 截取屏幕指定部分
    screenshot = pyautogui.screenshot(region=(left, top, width, height))
    # 将 PIL 图像转换为 numpy 数组
    screenshot_np = np.array(screenshot)

    # 使用 easyOCR 进行 OCR 识别
    # 创建 OCR 阅读器，根据源语言选择合适的语言
    source_lang = LANGUAGES[source_language_var.get()]
    if source_lang == 'en':
        reader = easyocr.Reader(['en'])
    elif source_lang == 'zh-CHS':
        reader = easyocr.Reader(['ch_sim'])
    elif source_lang == 'ja':
        reader = easyocr.Reader(['ja'])
    elif source_lang == 'ko':
        reader = easyocr.Reader(['ko'])
    elif source_lang == 'fr':
        reader = easyocr.Reader(['fr'])
    elif source_lang == 'de':
        reader = easyocr.Reader(['de'])
    elif source_lang == 'ru':
        reader = easyocr.Reader(['ru'])

    # 可以根据需要添加更多语言支持

    # 读取图像数据
    text = reader.readtext(screenshot_np)
    # print(text)
    # 输出识别结果
    full_text = ""
    for detection in text:
        # detection 是一个元组，detection[1] 是识别出的文本字符串
        print(detection[1])
        full_text += detection[1] + " "
    try:
        target_lang = LANGUAGES[target_language_var.get()]
        text, phonetic, translation = translate(full_text, source_lang, target_lang)
        show_translation_in_main(text, translation, phonetic)
        save_to_file(text, translation, phonetic)
    except Exception as e:
        error_label.config(text=f"翻译过程中出现错误: {e}")


def input_translate():
    input_text = input_entry.get()
    if input_text:
        try:
            source_lang = LANGUAGES[source_language_var.get()]
            target_lang = LANGUAGES[target_language_var.get()]
            text, phonetic, translation = translate(input_text, source_lang, target_lang)
            show_translation_in_main(text, translation, phonetic)
            save_to_file(text, translation, phonetic)
        except Exception as e:
            error_label.config(text=f"翻译过程中出现错误: {e}")


def show_translation_in_main(original_text, translation, phonetic):
    original_text_widget.delete(1.0, tk.END)
    original_text_widget.insert(tk.END, f"原文: {original_text}")

    phonetic_text_widget.delete(1.0, tk.END)
    phonetic_text_widget.insert(tk.END, f"音标: {phonetic}")

    translation_text_widget.delete(1.0, tk.END)
    translation_text_widget.insert(tk.END, f"翻译: {translation}")


def save_to_file(original_text, translation, phonetic):
    try:
        with open(file_path, 'a', encoding='utf-8') as f:
            f.write(f"原文: {original_text}\n")
            f.write(f"音标: {phonetic}\n")
            f.write(f"翻译: {translation}\n")
            f.write("-" * 50 + "\n")
        save_info_label.config(text="翻译结果已保存到 translation_history.txt 文件中。")
    except Exception as e:
        save_info_label.config(text=f"保存文件时出现错误: {e}")


# 创建主窗口
main_root = tb.Window(themename="flatly")
main_root.title("英文框选翻译软件")
main_root.geometry("500x700")  # 调整窗口大小以适应新组件

# 创建自定义样式来设置按钮字体
style = tb.Style()
style.configure('Custom.TButton', font=("Arial", 12))

# 创建语言选择下拉框
language_frame = tb.Frame(main_root)
language_frame.pack(pady=10)

source_language_var = tk.StringVar()
source_language_var.set('英文')
source_language_combobox = ttk.Combobox(language_frame, textvariable=source_language_var, values=list(LANGUAGES.keys()))
source_language_combobox.pack(side=tk.LEFT)

arrow_label = tb.Label(language_frame, text="→", font=("Arial", 12))
arrow_label.pack(side=tk.LEFT, padx=10)

target_language_var = tk.StringVar()
target_language_var.set('中文')
target_language_combobox = ttk.Combobox(language_frame, textvariable=target_language_var, values=list(LANGUAGES.keys()))
target_language_combobox.pack(side=tk.LEFT)

# 创建输入框和按钮用于手动输入翻译
input_frame = tb.Frame(main_root)
input_frame.pack(pady=10)
input_entry = tb.Entry(input_frame, font=("Arial", 12), width=30)
input_entry.pack(side=tk.LEFT)
input_button = tb.Button(input_frame, text="搜索", command=input_translate, bootstyle="primary", style='Custom.TButton')
input_button.pack(side=tk.LEFT, padx=5)

# 创建开始按钮
start_button = tb.Button(main_root, text="开始框选翻译", command=get_selection, bootstyle="success", style='Custom.TButton')
start_button.pack(pady=20)

# 创建用于显示原文、音标、翻译结果的文本框及滚动条
original_frame = tb.Frame(main_root)
original_frame.pack(pady=5)
original_scrollbar = tb.Scrollbar(original_frame)
original_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
original_text_widget = tb.Text(original_frame, wrap=tk.WORD, yscrollcommand=original_scrollbar.set, height=8, font=("Arial", 12))
original_text_widget.pack()
original_scrollbar.config(command=original_text_widget.yview)

phonetic_frame = tb.Frame(main_root)
phonetic_frame.pack(pady=5)
phonetic_scrollbar = tb.Scrollbar(phonetic_frame)
phonetic_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
phonetic_text_widget = tb.Text(phonetic_frame, wrap=tk.WORD, yscrollcommand=phonetic_scrollbar.set, height=2, font=("Arial", 12))
phonetic_text_widget.pack()
phonetic_scrollbar.config(command=phonetic_text_widget.yview)

translation_frame = tb.Frame(main_root)
translation_frame.pack(pady=5)
translation_scrollbar = tb.Scrollbar(translation_frame)
translation_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
translation_text_widget = tb.Text(translation_frame, wrap=tk.WORD, yscrollcommand=translation_scrollbar.set, height=8, font=("Arial", 12))
translation_text_widget.pack()
translation_scrollbar.config(command=translation_text_widget.yview)

# 创建用于显示保存信息和错误信息的标签
save_info_label = tb.Label(main_root, text="", font=("Arial", 12))
save_info_label.pack(pady=5)

error_label = tb.Label(main_root, text="", font=("Arial", 12), foreground="red")
error_label.pack(pady=5)

# 运行主循环
main_root.mainloop()